let run also with apply takeIf使用
let
let对对象T的扩展 ,接收的是T类型,返回的是R类型 。
- 有自己的作用域
- 作用域中的接收者是it
- 返回值,返回最后一个对象
1 | val result ="Hello World".let { |
输出结果
1 | System.out: Hello World |
使用?.let进行判断1
2
3
4
5
6
7private fun getInfo(jsonObject: JSONObject?): Info? {
return jsonObject?.let {
val uri = it.optString("uri")
val length = it.optString("length")
Info(uri, length)
}
}
这样写和用if判空的写法没有区别,实际上根据这段代码编译出的字节码反编译得到的java代码就是if…else…形式的。
在多重判断的时候使用,代码看起来更简洁
1 | // if...else...写法 |
let同时多重判断
1 | private fun multiJudge(a:String?,b:String?){ |
注意
let在括号里是可以进行重新命名的,但是箭头后面不能加大括号。如下
1 | fun letTest(a:String?){ |
run
- 有自己的作用域
- 作用域中的接收者是this
- 返回值,返回最后一个对象
1 |
|
run拥有一个单独的作用域,能够重新定义一个animal变量,并且它的作用域只存在于run函数当中。看起来好像没什么用处
1 | run { |
他的返回值是这个作用域的最后一个对象,上面的代码的话就会更简洁一些。而不是调用两次
1 | stringVariable?.run { |
和let的区别
能够为it重新命名。run不能够重新命名,如果我们不想覆盖外部作用域的this,这时候去使用T.let会更加的方便
also
- 有自己的作用域
- 作用域中的接收者 it
- 返回值都是原来的对象
1
2
3
4
5
6
7
8
9
10val original = "abc"
original.also {
println("The original String is $it") // "abc"
it.reversed()
}.also {
println("The reverse String is ${it}") // "abc"
it.length
}.also {
println("The length of the String is ${it}") // "abc"
}
T.also不管调用多少次返回的都是原来的original对象
对于T.let和T.also都能够进行链式操作,那么我们现在结合一下T.let和T.also的链式调用来看一下在实际场景中的应用。
//原始函数
1 | fun makeDir(path: String): File { |
apply
- 有自己的作用域
- 作用域中的接收者 this
- 返回值都是原来的对象
apply 和also的区别相当于 let 和run 的区别。一个接收this ,另一个是接收it 。同样的情况,also 是用重新命名。apply则不行。是链式结构创建一个Intent
1 | // 普通创建Intent方法 |
使用于建造者模式,apply则更经常使用。或者对同一对象多次操作,则apply 显现的代码更加的简洁。返回的是对象本身
1 | return TextView(context).apply { |
with
与run的方法类似 ,with(T)函数,而另一个则是使用了T.run函数。
with是传参进行处理。对于没什么判断的操作的时候使用情况都差不多
1 | with(webView.settings){ |
假设一种场景,那就是webView.settings可能为null。那我们就来再次看一下下面这段代码.
1 | with(webView.settings){ |
很明显run方法更好,可以在函数使用之前进行判断
takeIf
增加了判断,
1 | File(url).takeIf { it.exists() } |
takeIf 操作最后对象为Boolean ,当值是false时,则返回null ,返回值为true 则返回自身
在这里我们通过一个树状图来看一下对着五个标准函数的区别,使用以及如何选取标准函数